#ifndef _TEST_BOOST_ASIO_SERIAL_
#define _TEST_BOOST_ASIO_SERIAL_

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/noncopyable.hpp>
#include <algorithm>
#include <iostream>
#include <list>
#include <string>

using namespace boost::asio;

const unsigned long MAX_BUFFER_SIZE = 1024;
const unsigned long READ_THREAD_NUM = 10;

class SerialClient
{
private:
    serial_port sp_;

public:
    SerialClient(io_service &service) : sp_(service) {}

public:
    void open()
    {
        // 串口名称
        const std::string portName = "/dev/ttyS0";
        // 波特率
        unsigned int baudRate = 9600;
        // 数据位
        unsigned int dataBits = 8;
        // 停止位
        serial_port_base::stop_bits::type stopBits = serial_port_base::stop_bits::one;
        // 奇偶校验位
        serial_port_base::parity::type parity = serial_port_base::parity::none;
        // 流控
        serial_port_base::flow_control::type flowControl = serial_port_base::flow_control::none;

        // 设置串口参数
        sp_.set_option(boost::asio::serial_port_base::baud_rate(baudRate));
        sp_.set_option(boost::asio::serial_port_base::character_size(dataBits));
        sp_.set_option(boost::asio::serial_port_base::stop_bits(stopBits));
        sp_.set_option(boost::asio::serial_port_base::parity(parity));
        sp_.set_option(boost::asio::serial_port_base::flow_control(flowControl));

        // 打开串口
        sp_.open(portName);
    }
    void write()
    {
        // sp_.write_some();
    }
    void read()
    {
        // sp_.read_some();
    }
    void close()
    {
        // 关闭串口
        sp_.close();
    }
};

struct Client
{
    ip::tcp::socket socket;
    char buff[MAX_BUFFER_SIZE];
    unsigned long already_size;

    boost::mutex mutex;
    bool is_reading = false;

    bool set_reading()
    {
        boost::mutex::scoped_lock lock(mutex);
        if (is_reading)
        {
            return false;
        }
        else
        {
            is_reading = true;
            return true;
        }
    }
    bool unset_reading()
    {
        boost::mutex::scoped_lock lock(mutex);
        is_reading = false;
        return true;
    }
};

class AsioServer
{
private:
    io_service service;
    std::list<Client> clients;

public:
    AsioServer() = default;
    ~AsioServer() = default;

public:
    void open()
    {
    }
    void close() {}
    void handlerClientLoopy()
    {
        while (true)
        {
            // 多线程读取数据
            for (int i = 0; i < READ_THREAD_NUM; i++)
            {
                boost::thread(handleClientsThread);
            }
        }
    }
    void handleClientsThread()
    {
        for (auto &client : clients)
        {
            if (client.socket.is_open() && client.socket.available())
            {
                if (client.set_reading())
                {
                    // 加锁成功，读取数据
                    onRead(client);
                    client.unset_reading();
                }
            }
        }
    }
    void onRead(Client &client)
    {
        // 求得从缓存中取字节数
        int nextReadSize = std::min(MAX_BUFFER_SIZE - client.already_size, client.socket.available());

        // 从socket缓存中读取数据
        client.socket.read_some(buffer(client.buff + client.already_size, nextReadSize));
        // 更新已读取数据大小
        client.already_size += nextReadSize;

        // 查找是否包含结尾标识符,此处返回值为数组指针
        char *endFlagIndex = std::find(client.buff, client.buff + client.already_size, '\n');
        if (endFlagIndex < client.buff + client.already_size)
        {
            // 找到了标识符

            // 找到标识符的位置
            int pos = endFlagIndex - client.buff;
            // 获取一个完整消息
            std::string msg(client.buff, client.buff + pos);

            // 取出了pos个数据，更新已读取数据计数
            client.already_size -= pos;

            // 把client.buff中未读取的数据拷贝到它本身的开头，下次还从数组首地址开始取数据
            std::copy(client.buff + pos, client.buff + MAX_BUFFER_SIZE, client.buff);

            // 处理数据
            processMsg(client, msg);
        }
    }
    void processMsg(Client &client, std::string msg)
    {
        std::cout << "recv ----> " << msg << std::endl;
    }
    void onWrite() {}
};

class AsioClient
{
private:
    io_service service;

public:
    AsioClient() = default;
    ~AsioClient() = default;

public:
    void connect() {}
    void close() {}
    void onRead() {}
    void onWrite() {}
};

class AsyncServer : public boost::enable_shared_from_this<AsyncServer>, boost::noncopyable
{
private:
    ip::tcp::socket sock_;
    enum
    {
        max_msg = 1024
    };
    char read_buffer_[max_msg];
    char write_buffer_[max_msg];
    bool started_;

public:
    AsyncServer() = default;
    ~AsyncServer() = default;
    AsyncServer(io_service &service) : sock_(service), started_(false) {};

public:
    typedef AsyncServer self_type;

public:
    typedef boost::system::error_code error_code;
    typedef boost::shared_ptr<AsyncServer> ptr;
    void start()
    {
        io_service s;
        ip::tcp::socket sock_(s);
        started_ = true;
    }

    static ptr new_(io_service &service)
    {
        ptr new_(new AsyncServer(service));
        return new_;
    }
    void stop()
    {
        if (!started_)
            return;
        started_ = false;
    }
};

#endif